import React, { useImperativeHandle } from "react";
import "./index.css";
import { useControllableValue } from "ahooks";

interface CalendarProps {
	value?: Date;
	defaultValue?: Date;
	onChange?: (date: Date) => void;
}

interface CalendarRef {
	getDate: () => Date;
	setDate: (date: Date) => void;
}

const InternalCalendar: React.ForwardRefRenderFunction<
	CalendarRef,
	CalendarProps
> = (props, ref) => {
    /* 
    CustomCalendar2 使用了 ahooks 的 useControllableValue 来处理受控和非受控组件的场景。
    - useControllableValue 是一个增强的状态管理钩子，允许开发者灵活处理组件的 value 和 onChange 逻辑。
    - 如果父组件没有传入 value，组件会使用 defaultValue 来初始化；如果传入了 value，组件会完全受控。这提供了对 props 的更多灵活性和可控性。
    */
	const [date, setDate] = useControllableValue(props, {
		defaultValue: new Date(),
	});
    /* 
    useControllableValue 是一个可以处理受控与非受控状态的钩子。如果你传递了 value 属性，useControllableValue 会让组件成为受控组件，其状态将完全由 value 和 onChange 决定。
    如果没有传递 value 属性，组件会使用 defaultValue 来初始化并管理自己的状态。
    
    在这里：
        - props：包含父组件传递的 value 和 onChange 属性。
        - defaultValue：设置初始值，这里默认为当前日期 new Date()。
        - 具体来说，当父组件传递了 value：
            - useControllableValue 会使用 value 的值作为 date 的值，并监听 value 的变化。
            - 当父组件更新 value，date 也会随之更新。setDate 实际上将调用父组件的 onChange，以便让父组件更新 value。
            - 在这种情况下，CustomCalendar2 不管理自己的状态，而是由父组件管理。
        - 当父组件没有传递 value：
            - useControllableValue 将初始化为 defaultValue，即当前日期，并由 CustomCalendar2 内部管理其状态。
            - setDate 会更新 date，但不会调用 onChange，因为没有 value 提供，因此不依赖父组件管理。
    */


	useImperativeHandle(ref, () => {
		return {
			getDate() {
				return date;
			},
			setDate(date: Date) {
				setDate(date);
			},
		};
	});

	const handlePrevMonth = () => {
		setDate(new Date(date.getFullYear(), date.getMonth() - 1, 1));
	};

	const handleNextMonth = () => {
		setDate(new Date(date.getFullYear(), date.getMonth() + 1, 1));
	};

	const monthNames = [
		"一月",
		"二月",
		"三月",
		"四月",
		"五月",
		"六月",
		"七月",
		"八月",
		"九月",
		"十月",
		"十一月",
		"十二月",
	];

	const daysOfMonth = (year: number, month: number) => {
		return new Date(year, month + 1, 0).getDate();
	};

	const firstDayOfMonth = (year: number, month: number) => {
		return new Date(year, month, 1).getDay();
	};

	const renderDates = () => {
		const days = [];

		const daysCount = daysOfMonth(date.getFullYear(), date.getMonth());
		const firstDay = firstDayOfMonth(date.getFullYear(), date.getMonth());

		for (let i = 0; i < firstDay; i++) {
			days.push(<div key={`empty-${i}`} className="empty"></div>);
		}

		for (let i = 1; i <= daysCount; i++) {
			const clickHandler = () => {
				const curDate = new Date(
					date.getFullYear(),
					date.getMonth(),
					i
				);
				setDate(curDate);
			};

			if (i === date.getDate()) {
				days.push(
					<div
						key={i}
						className="day selected"
						onClick={() => clickHandler()}
					>
						{i}
					</div>
				);
			} else {
				days.push(
					<div key={i} className="day" onClick={() => clickHandler()}>
						{i}
					</div>
				);
			}
		}

		return days;
	};

	return (
        <div className="flexContainer jCCenter">
            	<div className="calendar">
                <div className="header">
                    <button onClick={handlePrevMonth}>&lt;</button>
                    <div>
                        {date.getFullYear()}年{monthNames[date.getMonth()]}
                    </div>
                    <button onClick={handleNextMonth}>&gt;</button>
                </div>
                <div className="days">
                    <div className="day">日</div>
                    <div className="day">一</div>
                    <div className="day">二</div>
                    <div className="day">三</div>
                    <div className="day">四</div>
                    <div className="day">五</div>
                    <div className="day">六</div>
                    {renderDates()}
                </div>
            </div>
        </div>
	
	);
};

const CustomCalendar2 = React.forwardRef(InternalCalendar);
export default CustomCalendar2

